package view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.stage.Stage;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.border.EtchedBorder;

import model.Conference;
import model.Database;
import model.Paper;
import model.User;

/**
 * This is the main panel for the program.
 * 
 * @author Greg Coleman
 * @author Rylie Nelson, Cody Thompson, Eric Preston
 */

public class MainPanel extends JPanel {

	private Paper selectedPaper;

	private Conference conference;

	private Database dbase;

	private MainFrame mf;

	private JPanel papPanel;

	private List<Paper> paps;

	private ArrayList<JButton> butts;

	private JPanel panelS;

	private MainPanel thisPan;

	final private Color grene = new Color(0,255,0);

	final private Color orig = new JButton().getBackground(); //original button color.

	/**
	 * Create a new MainPanel object.
	 * @param DB the database.
	 * @param mainf the parent frame.
	 */
	public MainPanel(Database DB, MainFrame mainf) {
		super();
		thisPan = this;
		dbase = DB;
		mf = mainf;
		conference = mf.getConf();
		init();
	}

	public void addPap(Paper pap) {
		pap.addAuthor(mf.getUser());
		//		paps.add(pap);
		mf.getConf().addPaper(pap);
		//		System.out.println("paper added");
		mf.redrawMainPanel();
	}

	public MainFrame getMF() {
		return mf;
	}

	/**
	 * Initialize the main panel with components.
	 */
	private void init() {
		setPreferredSize(new Dimension(800,600));
		setLayout(new BorderLayout());

		JScrollPane seeMeScrollin = new JScrollPane();

		JPanel panelN = new JPanel();
		add(panelN, BorderLayout.NORTH);
		panelN.setPreferredSize(new Dimension(800,100));

		JLabel lblConfName = new JLabel("New label");
		lblConfName.setHorizontalAlignment(SwingConstants.CENTER);
		lblConfName.setFont(new Font("Tahoma", Font.PLAIN, 30));
		panelN.add(lblConfName);
		lblConfName.setPreferredSize(new Dimension(300,75));
		lblConfName.setText(mf.getConf().toString());

		JPanel panelW = new JPanel();
		add(panelW, BorderLayout.WEST);
		panelW.setPreferredSize(new Dimension(50,400));

		panelS = new JPanel();
		add(panelS, BorderLayout.SOUTH);
		panelS.setPreferredSize(new Dimension(800,100));

		JButton exit = new JButton("Exit");
		JButton revs = new JButton("Display Reviews");
		JButton dl = new JButton("Download Paper");

		dl.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				dlPaper();
			}		
		});

		revs.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				dispRevs();
			}	
		});

		exit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					FileOutputStream fileOut = new FileOutputStream("somedata.ser");
					ObjectOutputStream out = new ObjectOutputStream(fileOut);
					out.writeObject(dbase);
					out.close();
					fileOut.close();
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				System.exit(0);
			}
		});

		prepButs();
		panelS.add(dl);
		panelS.add(revs);
		panelS.add(exit);

		JPanel panelE = new JPanel();
		add(panelE, BorderLayout.EAST);
		panelE.setPreferredSize(new Dimension(50,400));

		papPanel = new JPanel();
		papPanel.setPreferredSize(new Dimension(600,400));
		papPanel.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
		seeMeScrollin.setViewportView(papPanel);
		add(seeMeScrollin, BorderLayout.CENTER);
		GridBagLayout layout = new GridBagLayout();
		layout.rowHeights = new int[] {25};
		layout.columnWidths = new int[] {100};
		papPanel.setLayout(layout);
		populate();
	}

	/**
	 * Set up GridBagConstraints and populate the paper display window.
	 */
	private void populate() {
		
		GridBagConstraints title = new GridBagConstraints();
		title.weightx = 1.0;
		title.gridwidth = 1;
		title.anchor = GridBagConstraints.WEST;
		title.fill = GridBagConstraints.HORIZONTAL;
		title.gridy = 0;

		GridBagConstraints dline = new GridBagConstraints();
		dline.weightx = 1.0;
		dline.gridwidth = 1;
		dline.anchor = GridBagConstraints.WEST;
		dline.fill = GridBagConstraints.HORIZONTAL;
		dline.gridy = 0;

		GridBagConstraints status = new GridBagConstraints();
		status.weightx = 1.0;
		status.gridwidth = 2;
		status.anchor = GridBagConstraints.WEST;
		status.fill = GridBagConstraints.HORIZONTAL;
		status.gridy = 0;

		title.gridx = 0;
		dline.gridx = 1;
		status.gridx = 2;

		JLabel deadLabel = new JLabel("Deadline");
		deadLabel.setHorizontalAlignment(SwingConstants.CENTER);
		papPanel.add(new JLabel("Title"),title);
		papPanel.add(deadLabel,dline);
		papPanel.add(new JLabel("Status"),status);

		paps = mf.getConf().getPapers();
		butts = new ArrayList<JButton>();

		int count = 0;

		for (int i = 0; i < paps.size(); i++) { //add papers to list.

			if (mf.getAccess() == 2) { //is PC
				title.gridy = 0 + count + 1;
				dline.gridy = 0 + count + 1;
				status.gridy = 0 + count + 1;
				final Paper temp = paps.get(i);
				JButton b = buildButt(temp);
				butts.add(b);
				int date = count + 1;
				if (date > 12) {
					date = date % 12;
				}
				JLabel ARRRGH = new JLabel((date) + "/12/2013");
				ARRRGH.setHorizontalAlignment(SwingConstants.CENTER);
				papPanel.add(b,title);
				papPanel.add(ARRRGH,dline);
				count++;
				if (temp.isAccepted()) {
					papPanel.add(new JLabel("Accepted"),status);
				} else {
					papPanel.add(new JLabel("REJECTED"),status);
				}
			} else if (mf.getAccess() == 3 && paps.get(i).getSPC() != null && 
					paps.get(i).getSPC().getName().equals(mf.getUser().getName())) {
				title.gridy = 0 + count + 1;
				dline.gridy = 0 + count + 1;
				status.gridy = 0 + count + 1;
				final Paper temp = paps.get(i);
				JButton b = buildButt(temp);
				butts.add(b);
				int date = count + 1;
				if (date > 12) {
					date = date % 12;
				}
				JLabel ARRRGH = new JLabel((date) + "/12/2013");
				ARRRGH.setHorizontalAlignment(SwingConstants.CENTER);
				papPanel.add(b,title);
				papPanel.add(ARRRGH,dline);
				count++;
				if (temp.isAccepted()) {
					papPanel.add(new JLabel("Accepted"),status);
				} else {
					papPanel.add(new JLabel("REJECTED"),status);
				}
			} else if (mf.getAccess() == 0 && paps.get(i).getAuthor().equals(mf.getUser().getName())) {
				title.gridy = 0 + count + 1;
				dline.gridy = 0 + count + 1;
				status.gridy = 0 + count + 1;
				final Paper temp = paps.get(i);
				JButton b = buildButt(temp);
				butts.add(b);
				int date = count + 1;
				if (date > 12) {
					date = date % 12;
				}
				JLabel ARRRGH = new JLabel((date) + "/12/2013");
				ARRRGH.setHorizontalAlignment(SwingConstants.CENTER);
				papPanel.add(b,title);
				papPanel.add(ARRRGH,dline);
				count++;
				if (temp.isAccepted()) {
					papPanel.add(new JLabel("Accepted"),status);
				} else {
					papPanel.add(new JLabel("REJECTED"),status);
				}
			} else if (mf.getAccess() == 1 && paps.get(i).getReviewers().contains(mf.getUser())) {
				title.gridy = 0 + count + 1;
				dline.gridy = 0 + count + 1;
				status.gridy = 0 + count + 1;
				final Paper temp = paps.get(i);
				JButton b = buildButt(temp);
				butts.add(b);
				int date = count + 1;
				if (date > 12) {
					date = date % 12;
				}
				JLabel ARRRGH = new JLabel((date) + "/12/2013");
				ARRRGH.setHorizontalAlignment(SwingConstants.CENTER);
				papPanel.add(b,title);
				papPanel.add(ARRRGH,dline);
				count++;
				if (temp.isAccepted()) {
					papPanel.add(new JLabel("Accepted"),status);
				} else {
					papPanel.add(new JLabel("REJECTED"),status);
				}
			}

		}
	}

	/**
	 * prepare buttons based on access level.
	 */
	private void prepButs() {
		int al = mf.getAccess();
		if (al == 0) { //prepare author buttons
			JButton submit = new JButton("Submit Paper");

			submit.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					final JFXPanel upPap = new JFXPanel();
					panelS.add(upPap);					
					Platform.runLater(new Runnable() {
						@Override
						public void run() {
							Stage stage = new Stage();
							UploadPapers newPaper = new UploadPapers(thisPan);
							newPaper.start(stage);
						}
					});
				}
			});

			panelS.add(submit);

			JButton delete = new JButton("Delete Paper");

			delete.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					if (selectedPaper == null) {
						JOptionPane.showMessageDialog(null, "You need to select a paper first!");
					} else {
						JOptionPane.showMessageDialog(null, "I'm not going to ask if you're sure you want to delete or not. "
								+ "You're resigned to your fate.");
						int indexOfPap = paps.indexOf(selectedPaper);
						paps.remove(indexOfPap);
						mf.redrawMainPanel();
					}
				}

			});

			panelS.add(delete);

		} else if (al == 3) {
			JButton vRevies = new JButton("Display Reviewers");
			JButton subRec = new JButton("Submit Recommendation");
			JButton assRevs = new JButton("Assign Reviewers");
			//JButton changes = new JButton("Confirm Changes"); //maybe not needed

			subRec.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					RecForm rec;
					if (selectedPaper.getRecommendation() == null) {
						rec = new RecForm(selectedPaper, mf.getUser()); 
					} else {
						rec = new RecForm(selectedPaper, mf.getUser(), selectedPaper.getRecommendation()); 
					}
					rec.setDefaultCloseOperation(rec.DISPOSE_ON_CLOSE);
					rec.setVisible(true);
				}			
			});

			assRevs.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if (selectedPaper != null) {
						mf.launchRevSel(selectedPaper);
					} else {
						JOptionPane.showMessageDialog(null, "You need to select a paper first!");
					}
				}
			});

			vRevies.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					dispReviewers();
				}
			});
			panelS.add(vRevies);
			panelS.add(subRec);
			panelS.add(assRevs);
			//panelS.add(changes);
		} else if (al == 1) {
			JButton upRev =  new JButton("Upload/Edit Review");

			upRev.addActionListener(new ActionListener() {		
				@Override
				public void actionPerformed(ActionEvent e) {
					if (selectedPaper != null) {
						final JFXPanel upPap = new JFXPanel();
						panelS.add(upPap);					
						Platform.runLater(new Runnable() {
							@Override
							public void run() {
								Stage stage = new Stage();
								AddReview newPaper = new AddReview(thisPan, selectedPaper);
								newPaper.start(stage);
							}
						});
					} else {
						JOptionPane.showMessageDialog(null, "You need to select a paper first!");
					}
				}
			});
			panelS.add(upRev);
		} else if (al == 2) {
			JButton vRevies = new JButton("Display Reviewers");
			JButton accept =  new JButton("Accept Recommendation");
			JButton cSPC = new JButton("View Sub-Program Chair");

			cSPC.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if (selectedPaper != null) {
						if (selectedPaper.getSPC() != null) {
							JOptionPane.showMessageDialog(null, selectedPaper.getSPC().toString());
						} else {
							JOptionPane.showMessageDialog(null, "No Sub-Program Chair has been assigned.");
						}
					}
				}				
			});
			accept.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					//Paper tempPaper = selectedPaper;
					selectedPaper.setAccepted(true);
					mf.redrawMainPanel();
					//selectedPaper = tempPaper;
				}
			});

			JButton reject =  new JButton("Reject Recommendation");

			reject.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					//Paper tempPaper = selectedPaper;
					selectedPaper.setAccepted(false);
					mf.redrawMainPanel();
					//selectedPaper = tempPaper;
				}
			});

			JButton assiSPC =  new JButton("Assign Sub-program Chair");

			assiSPC.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if (selectedPaper != null) {
						mf.launchSPCSel(selectedPaper);
					} else {
						JOptionPane.showMessageDialog(null, "You need to select a paper first!");
					}
				}
			});

			JButton viewRec =  new JButton("View Recommendation");
			viewRec.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if (selectedPaper != null) {
						ViewRec recView = new ViewRec(selectedPaper.getRecommendation());
						recView.setDefaultCloseOperation(recView.DISPOSE_ON_CLOSE);
						recView.setVisible(true);
						recView.setLocationRelativeTo(null);
					} else {
						JOptionPane.showMessageDialog(null, "You need to select a paper first!");
					}
				}				
			});
			vRevies.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					dispReviewers();
				}
			});
			panelS.add(vRevies);
			panelS.add(accept);
			panelS.add(reject);
			panelS.add(assiSPC);
			panelS.add(viewRec);
			panelS.add(cSPC);
		}
	}

	/**
	 * Downloads the selected paper.
	 */
	private void dlPaper() {

		try {
			Desktop.getDesktop().open(selectedPaper.getPaper());
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Displays a list of the reviewers attached to this paper object.
	 */
	private void dispReviewers() {
		if (selectedPaper != null) {
			List<User> reviewers = selectedPaper.getReviewers();
			String revies = new String();
			if (!reviewers.isEmpty()) {
				for (int i = 0; i < reviewers.size(); i++) {
					revies += reviewers.get(i).toString() + "\n";
				}
				JOptionPane.showMessageDialog(null,revies);
			} else {
				JOptionPane.showMessageDialog(null,"There are no reviewers!");
			}
		} else {
			JOptionPane.showMessageDialog(null,"No paper is selected!");
		}
	}

	private void dispRevs() { //displays reviews
		if (selectedPaper != null) {
			ViewReview recView = new ViewReview(selectedPaper);
			recView.setDefaultCloseOperation(recView.DISPOSE_ON_CLOSE);
			recView.setVisible(true);
			recView.setLocationRelativeTo(null);
		} else {
			JOptionPane.showMessageDialog(null, "You need to select a paper first!");
		}
	}

	/**
	 * Button factory for making paper selection buttons
	 * @param p The paper the button selects.
	 * @return b A new button.
	 */
	private JButton buildButt(final Paper p) {
		final JButton b = new JButton(p.getTitle());
		b.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				for (int i = 0; i < butts.size(); i++) {
					if (butts.get(i) != b) {
						butts.get(i).setBackground(orig);
					}
				}
				if (b.getBackground() != grene) {
					b.setBackground(grene);
					selectedPaper = p;
				} else {
					b.setBackground(orig);
					selectedPaper = null;
				}
			}		
		});
		return b;
	}
}
